package com.hivekion.system.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.metadata.OrderItem;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.hivekion.common.entity.PagedResultVo;
import com.hivekion.common.entity.SearchInputVo;
import com.hivekion.common.entity.SelectOption;
import com.hivekion.common.exception.BusinessException;
import com.hivekion.common.security.SecurityUtils;
import com.hivekion.common.utils;
import com.hivekion.system.domain.SysRole;
import com.hivekion.system.domain.SysRolePermission;
import com.hivekion.system.domain.vo.*;
import com.hivekion.system.mapper.SysRoleMapper;
import com.hivekion.system.mapper.SysRolePermissionMapper;
import com.hivekion.system.service.ISysRoleService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

@Service
public class SysRoleServiceImpl implements ISysRoleService {

    @Autowired
    SysRoleMapper mapper;

    @Autowired
    SysRolePermissionMapper permissionMapper;

    @Override
    public SysRoleModelVo getInfo(String roleId) {
        SysRole role = getRoleModel(roleId);
        SysRoleModelVo modelVo = new SysRoleModelVo();
        BeanUtils.copyProperties(role, modelVo);
        return modelVo;
    }

    @Override
    public PagedResultVo<SysRoleModelVo> getList(SearchInputVo inputVo) {
        LambdaQueryWrapper<SysRole> wrapper = Wrappers.lambdaQuery();
        wrapper.and(
                StringUtils.isNotBlank(inputVo.getFilter()),
                t ->
                        t.like(SysRole::getRoleName, inputVo.getFilter())
                                .or()
                                .like(SysRole::getRemark, inputVo.getFilter()));
        Page<SysRole> rolePage = new Page<>(inputVo.getPageNum(), inputVo.getPageSize());
        rolePage.addOrder(new OrderItem("sort_code", true));
        rolePage.addOrder(new OrderItem("create_time", true));
        IPage<SysRole> roles = mapper.selectPage(rolePage, wrapper);
        List<SysRoleModelVo> list =
                roles.getRecords().stream()
                        .map(
                                item -> {
                                    SysRoleModelVo vo = new SysRoleModelVo();
                                    BeanUtils.copyProperties(item, vo);
                                    return vo;
                                })
                        .collect(Collectors.toList());
        Integer total = (int) roles.getTotal();
        PagedResultVo<SysRoleModelVo> resultVo =
                new PagedResultVo<SysRoleModelVo>(inputVo, total, list);
        return resultVo;
    }

    @Override
    public boolean add(SysRoleCreateInputVo inputVo) {
        if (!checkRoleNameUnique("", inputVo.getRoleName())) {
            throw new BusinessException(500, "新增角色'" + inputVo.getRoleName() + "'失败，角色名称已存在");
        }
        SysRole role = new SysRole();
        BeanUtils.copyProperties(inputVo, role);
        role.setCreateUserId(SecurityUtils.getUsername());
        return mapper.insert(role) > 0;
    }

    @Override
    public boolean edit(SysRoleUpdateInputVo inputVo) {
        if (!checkRoleNameUnique(inputVo.getId(), inputVo.getRoleName())) {
            throw new BusinessException(500, "修改角色'" + inputVo.getRoleName() + "'失败，角色名称已存在");
        }
        SysRole role = mapper.selectById(inputVo.getId());
        BeanUtils.copyProperties(inputVo, role);
        role.setUpdateUserId(SecurityUtils.getUsername());
        return mapper.updateById(role) > 0;
    }

    @Override
    public boolean remove(String roleId) {
        return mapper.deleteById(roleId) > 0;
    }

    @Override
    public boolean changeStatus(String roleId, Integer status) {
        SysRole role = getRoleModel(roleId);
        role.setStatus(status);
        return mapper.updateById(role) > 0;
    }

    private SysRole getRoleModel(String roleId) {
        SysRole role = mapper.selectById(roleId);
        if (role == null) {
            throw new BusinessException(500, "未找到角色信息！");
        }
        return role;
    }

    @Override
    public boolean checkRoleNameUnique(String roleId, String roleName) {
        SysRole info = mapper.checkRoleNameUnique(roleName);
        if (info != null && !info.getId().equals(roleId)) {
            return false;
        }
        return true;
    }

    @Override
    public List<SelectOption> getRoleOptions() {
        LambdaQueryWrapper<SysRole> wrapper = Wrappers.lambdaQuery();
        wrapper.eq(SysRole::getStatus, 0).and(t -> t.eq(SysRole::getDeleteMark, 0));
        List<SysRole> roles = mapper.selectList(wrapper);
        List<SelectOption> options =
                roles.stream()
                        .map(
                                item -> {
                                    SelectOption option = new SelectOption();
                                    option.setTitle(item.getRoleName());
                                    option.setValue(item.getId());
                                    option.setKey(item.getId());
                                    return option;
                                })
                        .collect(Collectors.toList());
        return options;
    }

    @Override
    public boolean setPermissions(SetRolePermissionVo vo) {
        SysRole role = mapper.selectById(vo.getRoleId());
        if (role == null) {
            throw new BusinessException(500, "未找到角色信息！");
        }
        QueryWrapper<SysRolePermission> queryWrapper = Wrappers.query();
        queryWrapper.eq("role_id", vo.getRoleId());
        List<String> oldList =
                permissionMapper.selectList(queryWrapper).stream()
                        .map(
                                item -> {
                                    return item.getMenuId();
                                })
                        .collect(Collectors.toList());
        List<String> newList = Arrays.asList(vo.getMenuIds());
        List<String> removeList = utils.diffList(oldList, newList); // 需要删除的角色
        List<String> addList = utils.diffList(newList, oldList); // 需要增加的角色
        if (removeList.size() > 0) {
            QueryWrapper<SysRolePermission> removeQueryWrapper = Wrappers.query();
            removeQueryWrapper.in("menu_id", removeList);
            permissionMapper.delete(removeQueryWrapper);
        }
        if (addList.size() > 0) {
            this.addRolePermission(role, addList);
        }
        return true;
    }

    @Override
    public SysRolePermissionsModelVo getPermissions(String roleId) {
        List<SysRolePermissionModelVo> allPermission = mapper.GetRolePermission(roleId);
        SysRolePermissionsModelVo vo = new SysRolePermissionsModelVo();
        List<String> menus =
                allPermission.stream()
                        .filter(t -> t.getMenuType() != null && t.getMenuType().equals(2))
                        .map(item -> item.getMenuId())
                        .collect(Collectors.toList());
        List<String> buttons =
                allPermission.stream()
                        .filter(t -> t.getMenuType() != null && t.getMenuType().equals(3))
                        .map(item -> item.getMenuId())
                        .collect(Collectors.toList());
        vo.setButtons(buttons);
        vo.setMenus(menus);
        return vo;
    }

    @Override
    public SysRole queryRole(String roleId) {
        return mapper.selectById(roleId);
    }

    @Override
    public SysRole queryRoleByName(String roleName) {
        LambdaQueryWrapper<SysRole> wrapper = Wrappers.lambdaQuery();
        LambdaQueryWrapper<SysRole> queryCondition = wrapper.eq(SysRole::getRoleName, roleName);
        return mapper.selectOne(queryCondition);
    }

    private void addRolePermission(SysRole role, List<String> list) {
        if (list != null && list.size() > 0) {
            list.stream()
                    .forEach(
                            item -> {
                                SysRolePermission model = new SysRolePermission();
                                model.setMenuId(item.trim());
                                model.setRoleId(role.getId());
                                permissionMapper.insert(model);
                            });
        }
    }
}
